const fs = require('fs');
const path = require('path');
const JavaScriptObfuscator = require('javascript-obfuscator');
const bytenode = require('bytenode');
const { execSync } = require('child_process');

class SecureBuildTool {
  constructor() {
    this.srcDir = path.join(__dirname, '../src');
    this.outDir = path.join(__dirname, '../out');
    this.tempDir = path.join(__dirname, '../temp-build');
    
    // 检查是否仅混淆模式
    this.obfuscateOnly = process.argv.includes('--obfuscate-only');
    
    this.obfuscatorOptions = {
      compact: true,
      controlFlowFlattening: true,
      controlFlowFlatteningThreshold: 1,
      numbersToExpressions: true,
      simplify: true,
      stringArrayShuffle: true,
      splitStrings: true,
      stringArrayThreshold: 1,
      transformObjectKeys: true,
      unicodeEscapeSequence: false,
      deadCodeInjection: true,
      deadCodeInjectionThreshold: 1,
      debugProtection: true,
      debugProtectionInterval: 4000,
      disableConsoleOutput: true,
      identifierNamesGenerator: 'hexadecimal',
      log: false,
      stringArray: true,
      stringArrayEncoding: ['base64'],
      stringArrayIndexShift: true,
      stringArrayRotate: true,
      stringArrayWrapperName: 'obf',
      target: 'node',
      seed: Math.floor(Math.random() * 1000000)
    };
  }

  // 清理临时目录
  cleanTemp() {
    if (fs.existsSync(this.tempDir)) {
      fs.rmSync(this.tempDir, { recursive: true, force: true });
    }
    fs.mkdirSync(this.tempDir, { recursive: true });
  }

  // 复制源文件到临时目录
  copySource() {
    console.log('📂 复制源文件...');
    this.copyRecursive(this.srcDir, this.tempDir);
  }

  copyRecursive(src, dest) {
    const stats = fs.statSync(src);
    if (stats.isDirectory()) {
      if (!fs.existsSync(dest)) {
        fs.mkdirSync(dest, { recursive: true });
      }
      fs.readdirSync(src).forEach(item => {
        this.copyRecursive(path.join(src, item), path.join(dest, item));
      });
    } else {
      fs.copyFileSync(src, dest);
    }
  }

  // 混淆JavaScript文件
  obfuscateFiles() {
    console.log('🔒 开始代码混淆...');
    this.processDirectory(this.tempDir);
  }

  processDirectory(dir) {
    const files = fs.readdirSync(dir);
    
    files.forEach(file => {
      const filePath = path.join(dir, file);
      const stats = fs.statSync(filePath);
      
      if (stats.isDirectory()) {
        this.processDirectory(filePath);
      } else if (path.extname(file) === '.js') {
        this.obfuscateFile(filePath);
      }
    });
  }

  obfuscateFile(filePath) {
    try {
      console.log(`  混淆文件: ${path.relative(this.tempDir, filePath)}`);
      const code = fs.readFileSync(filePath, 'utf8');
      
      // 跳过某些特殊文件
      if (this.shouldSkipFile(filePath, code)) {
        console.log(`    跳过: ${path.basename(filePath)}`);
        return;
      }
      
      const obfuscatedResult = JavaScriptObfuscator.obfuscate(code, this.obfuscatorOptions);
      fs.writeFileSync(filePath, obfuscatedResult.getObfuscatedCode());
    } catch (error) {
      console.warn(`    警告: 混淆失败 ${filePath}:`, error.message);
    }
  }

  shouldSkipFile(filePath, code) {
    const filename = path.basename(filePath);
    
    // 只跳过真正有问题的特定模式
    // 跳过明显的配置文件
    if (filename === 'knexfile.js' || filename.startsWith('knex.config')) {
      return true;
    }
    
    // 跳过包含复杂路径操作的数据库配置（但允许简单的数据库操作）
    if (filename.includes('database') && code.includes('getUserDataPath')) {
      return true;
    }
    
    // 跳过包含复杂模板字符串的文件
    if (code.includes('${') && code.includes('resolve(') && code.includes('temp-build')) {
      return true;
    }

    return false;
  }

  // V8字节码编译（可选，如果有问题则跳过）
  compileToBytenode() {
    console.log('⚡ 尝试编译为V8字节码...');
    
    const mainFiles = [
      path.join(this.tempDir, 'main/index.js'),
      path.join(this.tempDir, 'preload/index.js')
    ];
    
    let bytecodeSuccess = false;
    
    mainFiles.forEach(file => {
      if (fs.existsSync(file)) {
        try {
          console.log(`  尝试编译: ${path.relative(this.tempDir, file)}`);
          
          // 读取原始文件内容备份
          const originalContent = fs.readFileSync(file, 'utf8');
          
          // 尝试编译为字节码
          const jscFile = file.replace('.js', '.jsc');
          
          // 使用更安全的编译方式
          try {
            bytenode.compileFile(file, jscFile);
            
            // 检查字节码文件是否成功创建
            if (fs.existsSync(jscFile) && fs.statSync(jscFile).size > 0) {
              // 创建备用文件
              const backupFile = file.replace('.js', '.backup.js');
              fs.writeFileSync(backupFile, originalContent);
              
              // 使用带错误处理的加载器
              const relativePath = './' + path.basename(jscFile);
              const backupPath = './' + path.basename(backupFile);
              const loaderContent = `try {
  require('bytenode');
  require('${relativePath}');
} catch (error) {
  // 如果字节码加载失败，回退到备用代码
  console.warn('字节码加载失败，使用备用代码:', error.message);
  require('${backupPath}');
}`;
              
              fs.writeFileSync(file, loaderContent);
              bytecodeSuccess = true;
              console.log(`    ✅ 字节码编译成功（带备用机制）`);
            } else {
              console.log(`    ⚠️ 字节码文件无效，保持原文件`);
              // 保持原文件内容
              fs.writeFileSync(file, originalContent);
            }
          } catch (compileError) {
            console.warn(`    ⚠️ 字节码编译失败，保持原文件:`, compileError.message);
            // 保持原文件内容
            fs.writeFileSync(file, originalContent);
          }
        } catch (error) {
          console.warn(`    ⚠️ 处理文件失败:`, error.message);
        }
      }
    });
    
    if (!bytecodeSuccess) {
      console.log('  📝 注意：字节码编译未成功，但代码混淆仍然有效');
    }
  }

  // 复制字节码文件到输出目录
  copyBytecodeFiles() {
    if (this.obfuscateOnly) {
      return; // 仅混淆模式不需要复制字节码文件
    }

    console.log('📎 复制字节码文件...');
    
    const bytecodeFiles = [
      { src: path.join(this.tempDir, 'main/index.jsc'), dest: path.join(this.outDir, 'main/index.jsc') },
      { src: path.join(this.tempDir, 'preload/index.jsc'), dest: path.join(this.outDir, 'preload/index.jsc') }
    ];
    
    // 同时复制备用文件
    const backupFiles = [
      { src: path.join(this.tempDir, 'main/index.backup.js'), dest: path.join(this.outDir, 'main/index.backup.js') },
      { src: path.join(this.tempDir, 'preload/index.backup.js'), dest: path.join(this.outDir, 'preload/index.backup.js') }
    ];
    
    [...bytecodeFiles, ...backupFiles].forEach(({ src, dest }) => {
      if (fs.existsSync(src)) {
        console.log(`  复制: ${path.basename(src)}`);
        // 确保目标目录存在
        const destDir = path.dirname(dest);
        if (!fs.existsSync(destDir)) {
          fs.mkdirSync(destDir, { recursive: true });
        }
        fs.copyFileSync(src, dest);
      }
    });
  }

  // 运行Electron-Vite构建
  buildWithVite() {
    console.log('🏗️ 运行Electron-Vite构建...');
    
    // 临时修改electron.vite.config.js以使用临时目录
    const configPath = path.join(__dirname, '../electron.vite.config.js');
    const originalConfig = fs.readFileSync(configPath, 'utf8');
    
    const secureConfig = originalConfig.replace(
      /resolve\('src\//g,
      `resolve('temp-build/`
    );
    
    fs.writeFileSync(configPath, secureConfig);
    
    try {
      execSync('npm run build', { stdio: 'inherit', cwd: path.join(__dirname, '..') });
      
      // 复制字节码文件到输出目录
      this.copyBytecodeFiles();
    } finally {
      // 恢复原始配置
      fs.writeFileSync(configPath, originalConfig);
    }
  }

  // ASAR加密（注意：真正的ASAR加密需要修改Electron源码）
  enableAsarEncryption() {
    console.log('🔐 配置ASAR保护...');
    
    // 这里我们使用ASAR的完整性保护和代码混淆
    // 真正的ASAR加密需要自定义Electron构建
    const packageJsonPath = path.join(__dirname, '../package.json');
    const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
    
    // 配置ASAR选项
    packageJson.build.asar = {
      smartUnpack: false
    };
    
    // 添加文件完整性检查和字节码依赖
    packageJson.build.asarUnpack = [
      "node_modules/better-sqlite3/**/*",
      "node_modules/knex/**/*",
      "node_modules/bytenode/**/*"
    ];
    
    fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
  }

  // 清理临时文件
  cleanup() {
    console.log('🧹 清理临时文件...');
    if (fs.existsSync(this.tempDir)) {
      fs.rmSync(this.tempDir, { recursive: true, force: true });
    }
  }

  // 主构建流程
  async build() {
    const mode = this.obfuscateOnly ? '混淆' : '安全';
    console.log(`🚀 开始${mode}构建流程...\n`);
    
    try {
      this.cleanTemp();
      this.copySource();
      this.obfuscateFiles();
      
      // 仅在完整安全模式下进行字节码编译
      if (!this.obfuscateOnly) {
        this.compileToBytenode();
      } else {
        console.log('📝 仅混淆模式，跳过字节码编译');
      }
      
      this.enableAsarEncryption();
      this.buildWithVite();
      
      console.log(`\n✅ ${mode}构建完成！`);
    } catch (error) {
      console.error('❌ 构建失败:', error);
      throw error;
    } finally {
      this.cleanup();
    }
  }
}

// 运行构建
if (require.main === module) {
  const builder = new SecureBuildTool();
  builder.build().catch(console.error);
}

module.exports = SecureBuildTool;